package com.zhu.algorithm.loadBalance.random;

import com.zhu.algorithm.loadBalance.ServerIps;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: zhujiabao
 * @Date: 2022/06/08/6:49
 * @Description:随机策略
 */
public class Random {

    /**
     * 普通版随机策略
     * @return服务器IP
     */
    public static String getServer() {

        java.util.Random random = new java.util.Random();

        int pos = random.nextInt(ServerIps.LIST.size());

        return ServerIps.LIST.get(pos);
    }

    /**
     * 权重版随机策略 （用权重去复制ip），耗内存
     * @return 服务器IP
     */
    public static String getServerOfWeight() {

        List<String> ipList = new ArrayList<>();
        for (String ip : ServerIps.WEIGHT_MAP.keySet()) {
            Integer weight = ServerIps.WEIGHT_MAP.get(ip);
            for (int i = 0; i < weight; i++) {
                ipList.add(ip);
            }
        }
//        System.out.println(ipList.toString());
        java.util.Random random = new java.util.Random();

        int pos = random.nextInt(ipList.size());

        return ipList.get(pos);
    }

    /**
     * 权重版随机策略 （用区间去模拟ip的权重），较优
     * @return 服务器IP
     *
     * 再调优：当权重全部相等时，权重可以忽略，此时可以采用简单随机。
     */
    public static String getServerOfWeightRange() {

        //权重全部相等标志
        boolean weightEqualsFlag = false;

        //将服务器的权重放在一个list集合中
        List<Integer> weightList = new ArrayList<>(ServerIps.WEIGHT_MAP.values());

        //求权重总和
        int sumWeight = weightList.stream().reduce(Integer::sum).orElse(0);

        //判断是否权重全部相等
        Set s = new HashSet(weightList);
        if (s.size() == 1) {
            weightEqualsFlag = true;
        }

        if (weightEqualsFlag == false) {
            //生成一个随机数
            java.util.Random random = new java.util.Random();
            int randomPos = random.nextInt(sumWeight);

            //在 WEIGHT_MAP 中取出一个 ip 值和权重值，并判断该随机数是否小于这个权重值。若小于则取这个权重值，则选取对应的ip值；否者用这个随机数减去这个权重值，
            for (String ip : ServerIps.WEIGHT_MAP.keySet()) {
                Integer weight = ServerIps.WEIGHT_MAP.get(ip);
                if (randomPos < weight) {
                    return ip;
                }
                randomPos = randomPos - weight;
            }
        }

        return (String) ServerIps.WEIGHT_MAP.keySet().toArray()[new java.util.Random().nextInt(ServerIps.WEIGHT_MAP.values().size())];

    }

    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
//            System.out.println(getServer());
//            System.out.println(getServerOfWeight());
            System.out.println(getServerOfWeightRange());
        }

    }

}
